//----------------------------------------------------------------------------
//  ,-.
// /_\___ ,   Ninja Framework
// '  ___\    (C) Riccardo Capra - http://riccar.do
//  //   \\
//----------------------------------------------------------------------------
//  This program is free software: you can redistribute it and/or modify
//  it under the terms of the GNU General Public License as published by
//  the Free Software Foundation, either version 3 of the License, or
//  (at your option) any later version.
//
//  This program is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//  GNU General Public License for more details.
//
//  You should have received a copy of the GNU General Public License
//  along with this program.  If not, see <http://www.gnu.org/licenses/>.
//----------------------------------------------------------------------------

#ifndef NJ_PLACEMENT_NEW_H
#	define NJ_PLACEMENT_NEW_H

#	include "NjExample01.h"

	/// \brief Helper class to implement the placement new
	class NjPlacementNew
	{
	public:
		NJ_TRIVIAL_DESTRUCTOR(NjPlacementNew);

		/// \brief Creates a NjPlacementNew instance
		///
		/// The istance is not initialized. 
		/// On some build configurations it will be asserted if used not initialized
		NjPlacementNew();

		/// \brief Creates a NjPlacementNew instance copying the value from \em pAddress
		/// 
		/// \em pAddress should be not NJ_NULL
		NjPlacementNew(void * pAddress);

		/// \brief Creates a NjPlacementNew instance copying the value from \em kAddress
		/// 
		/// \em kAddress should be initialized
		NjPlacementNew(NjPlacementNew const & kAddress);

		/// \brief Copies a the value from \em kAddress
		/// 
		/// \em kAddress should be initialized
		NjPlacementNew & operator=(NjPlacementNew const & kAddress);

		/// \brief Returns the address stored internally
		void * GetAddress() const;

		/// \brief Updates the value from \em pAddress
		/// 
		/// \em pAddress should be not NJ_NULL
		void SetAddress(void * pAddress);

	private:
		/// \brief The address value
		void * m_pAddress;
	};

	/// \brief Creates a new instance of size \em uSize using the placement address \em kPlacement
	void * operator new(size_t uSize, NjPlacementNew const & kPlacement);

	/// \brief Creates a new array of size \em uSize using the placement address \em kPlacement
	void * operator new[](size_t uSize, NjPlacementNew const & kPlacement);

	/// \brief This is required by the compiler just for handle exceptions
	///
	/// It does nothing but on some build configurations it will assert
	void operator delete(void * pAddress, NjPlacementNew const & kPlacement);

	/// \brief This is required by the compiler just for handle exceptions
	///
	/// It does nothing but on some build configurations it will assert
	void operator delete[](void * pAddress, NjPlacementNew const & kPlacement);

	/// \brief Placement new macro
	/// \param kPlacement an NjPlacementNew instance
	/// \param xAll the type to be allocated
	/// \sa NjNew
#	define NJ_PLACEMENT_NEW(kPlacement, xAll) (::new(kPlacement) xAll)

	/// \brief Placement new array macro
	/// \param kPlacement an NjPlacementNew instance
	/// \param xAll the type and array size to be allocated
	/// \sa NjNewArray
#	define NJ_PLACEMENT_NEW_ARRAY(kPlacement, xAll) (::new(kPlacement) xAll)

#	include "NjPlacementNew_inline.h"

#endif // NJ_PLACEMENT_NEW_H
